package dao

import (
	"github.com/fsnotify/fsnotify"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	"github.com/kotlin2018/mbt"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/spf13/viper"
	"io"
	"log"
	"time"
)

var (
	Cfg Config
	DB  *sqlx.DB
)

// 全局总配置文件的配置结构体
type Config struct {
	Database *mbt.Database //第一个数据库的配置项
	Server   *Server
	Email    *Email
	OSS      *OSS
	JWT 	 *JWT
}

func init() {
	v := viper.New()
	v.SetConfigFile("./config.toml")
	err := v.ReadInConfig()
	if err != nil {
		log.Fatalln("Fatal error config file :", err.Error())
	}
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		log.Println("config file changed:", in.Name)
		if err = v.Unmarshal(&Cfg); err != nil {
			log.Fatalln(err)
		}
	})

	if err = v.Unmarshal(&Cfg); err != nil {
		log.Fatalln(err)
	}
}
func init() {
	engine, db, err := mbt.New(Cfg.Database)
	if err != nil {
		log.Fatalln(err)
	}
	DB = sqlx.NewDb(db, Cfg.Database.DriverName)
	engine.Register(initMapper())
	engine.SetOutPut(initLogger(Cfg.Database.Logger.Path, Cfg.Database.Logger.MaxAge, Cfg.Database.Logger.Interval))
	//engine.Run()
}

func initMapper() map[interface{}]interface{} {
	h := mbt.H{
		&AdsContDao:         &AdsCont{},         // 广告表
		&AdsPositionDao:     &AdsPosition{},     // 广告位
		&AuthDao:            &Auth{},            // 用户权限关联表
		&BookDao:            &Book{},            // 书籍表
		&BookCategoryDao:    &BookCategory{},    // 书籍与分类关联表
		&BookCounterDao:     &BookCounter{},     // 书籍计数表
		&BookMarkDao:        &BookMark{},        // 书签
		&CategoryDao:        &Category{},        // 分类
		&CommentDao:         &Comment{},         // 评论表
		&DocumentDao:        &Document{},        // 文档表
		&DocumentHistoryDao: &DocumentHistory{}, // 文档历史表
		&DocumentStoreDao:   &DocumentStore{},   // 文档存储，将大内容分发到专门的数据表里面
		&DownloadCounterDao: &DownloadCounter{}, // 下载计数
		&FansDao:            &Fans{},            // 粉丝表
		&FriendLinkDao:      &FriendLink{},      // 友链数据表
		&LabelDao:           &Label{},           // 标签表
		&LogsDao:            &Logs{},            // 日志表
		&MemberDao:          &Member{},          // 成员表
		&MemberTokenDao:     &MemberToken{},     // 成员token表
		&MigrationDao:       &Migration{},       // 迁移
		&OptionDao:          &Option{},          //
		&PrintBookDao:       &PrintBook{},       //
		&QqDao:              &Qq{},              //
		&QueueDao:           &Queue{},           // 导出离线文档队列
		&ReadingTimeDao:     &ReadingTime{},     // 阅读时长
		&ReadRecordDao:      &ReadRecord{},      // 阅读记录.用于记录阅读的文档，以及阅读进度统计
		&RegLimitDao:        &RegLimit{},        //
		&RelateBookDao:      &RelateBook{},      //
		&RelationShipDao:    &RelationShip{},    //
		&ScoreDao:           &Score{},           // 评分表
		&SeoDao:             &Seo{},             //
		&SignDao:            &Sign{},            // 会员签到表
		&SpiderDao:          &Spider{},          // 爬虫表
		&StarDao:            &Star{},            //
		&SubmitBookDao:      &SubmitBook{},      //
		&WechatDao:          &Wechat{},          // 微信
		&WechatCodeDao:      &WechatCode{},      // 微信小程序码记录表
	}
	return h
}

func initLogger(path string, maxAge, interval int) io.Writer {
	/* 日志轮转相关函数
	WithLinkName() 	 为最新的日志建立软连接
	WithRotationTime()  设置日志分割的时间，隔多久分割一次
	WithMaxAge() 和 WithRotationCount() 二者只能设置一个
	WithMaxAge()  		 设置文件清理前的最长保存时间
	WithRotationCount() 设置文件清理前最多保存的个数
	*/
	// 下面配置日志每隔 interval 秒轮转一个新文件，保留最近 maxAge 秒的日志文件，多余的自动清理掉。
	writer, _ := rotatelogs.New(
		path+".%Y%m%d%H%M",
		rotatelogs.WithLinkName(path),
		rotatelogs.WithMaxAge(time.Duration(maxAge)*time.Hour),
		rotatelogs.WithRotationTime(time.Duration(interval)*time.Hour),
	)
	return writer
}
